package com.omesoft.hksnore.util.newsnore;


import android.content.Context;
import android.os.Handler;
import android.os.Message;

import com.omesoft.hksnore.util.L;
import com.omesoft.hksnore.util.constant.CusConstant;
import com.omesoft.hksnore.util.data.MySharedPreferencesUtil;

public class ClacSnore {
    private static final int maxColums = 128;
    private static final int Y0 = 1 << ((FFT.FFT_N_LOG + 3));
    private static final double logY0 = Math.log10(Y0); // lg((8*FFT_N)^2)

    private int band = 64;

    private int[] xplot;
    private int[] spectremS;

    private Context context;

    private Handler handler;

    private long startTime;
//    TxtWrite tw;


    public ClacSnore(Handler _handler, Context _context) {
        // this.band = band;
        // deltax = (width - band + 1) / band + 1;his
        this.handler = _handler;
        this.context = _context;
        startTime = System.currentTimeMillis();
        String ss = String.valueOf(System.currentTimeMillis());
//        tw = new TxtWrite("-" + ss.substring(ss.length() - 9, ss.length() - 3));
        xplot = new int[maxColums + 1];
        spectremS = new int[band];
        // 0-16kHz分划为band个频段，各频段宽度非线性划分。
        for (int i = 0; i <= band; i++) {
            xplot[i] = 0;
            xplot[i] = (int) (0.5 + Math.pow(FFT.FFT_N >> 1, (double) i / band));
            if (i > 0 && xplot[i] <= xplot[i - 1])
                xplot[i] = xplot[i - 1] + 1;
        }
    }

    public int lastWave = 0;
    public long lastStart = 0;
    public long lastEnd = 0;
    public boolean isSnore = false;
    public int actCount = 0;// 体动次数
    public int turnCount = 0;
    public int snoreCount = 0;
    public int snoreDuration = 0;
    public int snoreRate = 0;
    public int snoreCountN = 0;
    public int stopSnoreCount = 0;
    public int sumcurWave32 = 0, sumcurWave64 = 0;
    private long lastVBTime = 0;// 上一次振动的时间
    double op = 0;
    double opHB[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
    long curEnd = 0, crest = 0, cycle = 0;
    int curWave32 = 0, curWave64 = 0;
    float pensent = 0.0f;
    int actPr = 0;// 每100毫秒的计数
    int actN = 0;// 有多少条数据
    int vbLv = 0;
    int Hour = 360000;

    public void analysis(float[] amp) {
        int i = 0, y, xi;
        float maxAmp;
        for (; i != band; i++) {
            // 查找当前频段的最大"幅值"
            maxAmp = 0;
            xi = xplot[i];
            y = xplot[i + 1];
            for (; xi < y; xi++) {
                if (amp[xi] > maxAmp)
                    maxAmp = amp[xi];
            }
            // y =(int) ((Math.log10(maxAmp) - logY0) * 20);
            y = (maxAmp > Y0) ? (int) ((Math.log10(maxAmp) - logY0) * 20) : 0;
            spectremS[i] = y;

        }
        clacEuclidean(spectremS, System.currentTimeMillis());

        // if ((sumcurWave32 + curWave64) > 0) {
        String writeStr = "";
        for (int j = 0; j < spectremS.length; j++) {
            writeStr += spectremS[j] + ",";
        }
//        System.out.print("\n" + new TimeUtil().getNowDate() + "," + writeStr);
//        tw.write("\n" + new TimeUtil().getNowDate() + "," + writeStr);// 写入TXT
        // }

    }

    public void clacEuclidean(int[] spectremS, long curTime) {
        op = 0;
        curEnd = 0;
        crest = 0;
        cycle = 0;
        curWave32 = 0;
        curWave64 = 0;
        pensent = 0.0f;

        int i = 0;
        for (; i < spectremS.length; i++) {
            // 查找当前频段的最大"幅值"

            if (i < 40) {// 每个值对应64HZ，在45之前都是一对一的，所以 800HZ对应第12.5个值
                curWave32 += spectremS[i];
                op = (op + Math
                        .pow((DataAry.snoreSample1[i] - spectremS[i]), 2));// 先求平方和
            } else {
                curWave64 += spectremS[i];
                op = (op - Math
                        .pow((DataAry.snoreSample1[i] - spectremS[i]), 2));// 先求平方和
            }
            if (i < 53 && i > 12 && spectremS[i] > 0) {
                actPr++;
            }
        }
        if (curWave32 != 0) {
            actN++;
        }
        // System.out.print(getNowDate() + op + ",");
        sumcurWave32 += curWave32;
        sumcurWave64 += curWave64;
        int sum = sumcurWave32 + sumcurWave64 + 1;
        pensent = (sumcurWave32 * 1.0f) / (sum * 1.0f);
        if (lastWave == 0 && curWave32 != 0) {// start
            lastStart = curTime;
            actN = 1;
        } else if (lastWave != 0 && curWave32 == 0) {// end
            curEnd = curTime;
            crest = curEnd - lastStart;// 波峰时长
            cycle = curEnd - lastEnd;// 周期时长
            L.e("xxx","crest="+crest +"  pensent="+pensent +"  sumcurWave32="+ sumcurWave32 );

            if (crest > 500 && crest < 3000 && pensent > 0.9 && sumcurWave32 > 300) {// 符合鼾声周期，
                System.out.print("xxx" + new TimeUtil().getTimeStr(curTime)
                        + "符合鼾声波峰 crest：" + crest + " op：" + op + " curWave32:"
                        + curWave32 + " curWave64:" + curWave64
                        + " sumcurWave32:" + sumcurWave32 + " sumcurWave64:"
                        + sumcurWave64 + " pensent" + pensent);
                if (cycle > 3000 && cycle < 8000) {
                    isSnore = true;
                    if (snoreCountN == 0) {
                        snoreDuration += cycle;
                        snoreCount++;
                        snoreCountN++;
                    }
                    snoreDuration += cycle;
                    snoreCount++;
                    snoreCountN++;
                    snoreRate = Math.round(60000 * snoreCount / snoreDuration);
                    System.out.print("\n" + new TimeUtil().getTimeStr(curTime)
                            + "打鼾了：");
                    System.out.print("+snoreCount:" + snoreCount + ","
                            + "+snoreDuration:" + snoreDuration + ","
                            + "+snoreRate:" + snoreRate + ",");
                    long durTime = curTime - lastVBTime;

                    sendMsg(CusConstant.SNORE_COUNT, snoreCount);
                    sendMsg(CusConstant.SNORE_TIME, snoreDuration / 1000);
                    sendMsg(CusConstant.BREATH_RATE, snoreRate);
                    /**
                     * 加入对入眠时间的判断，开始时间大于入眠时间才计算止鼾和发送止鼾指令
                     * */
                    if (snoreCountN > 3 && System.currentTimeMillis() - startTime > MySharedPreferencesUtil.getInSleepTime(context) * 1000 * 60) {
                        clacStopSnoreLV(durTime);//发送止鼾等级之前调整止鼾等级
                        vbLv++;
                        stopSnoreCount++;
                        sendMsg(CusConstant.SNORE_STOP_COUNT, stopSnoreCount);
                        L.e("SNORE_STOP_COUNT   "
                                + new TimeUtil().getTimeStr(curTime) + "启动止鼾："
                                + stopSnoreCount + "次" + "连续鼾声" + snoreCountN);
                        //发送handler信息
                        if (vbLv > MySharedPreferencesUtil.getMaxVbLv(context)) {//不能超过最大等级
                            vbLv = MySharedPreferencesUtil.getMaxVbLv(context);
                        }
                        sendMsg(CusConstant.SNORE_STOP, vbLv);//发送止鼾等级
                        MySharedPreferencesUtil.setVbLv(context, vbLv);//保存止鼾等级
                        lastVBTime = curTime;
                        snoreCountN = 0;
                    }
                } else {

                    if (actPr > actN * 5 * 0.6f) {
                        System.out.print("\n" + new TimeUtil().getTimeStr(curTime)
                                + "有体动了：actCount::" + actCount + "::turnCount::"
                                + turnCount);
                        actCount++;// 体动次数
                        sendMsg(CusConstant.ACT_COUNT, actCount);//发送体动次数
                        if (crest > 200) {
                            turnCount++;
                            sendMsg(CusConstant.TRUN_COUNT, turnCount);//发送翻身次数
                        }
                    }
                    snoreCountN = 0;
                }
                lastEnd = curTime;

            } else {
                isSnore = false;
                System.out.print("\n" + new TimeUtil().getTimeStr(curTime)
                        + "计算体动翻身：actPr::" + actPr + "::actN::" + actN
                        + "：：大小：：" + (actN * 10 * 0.6f));

                if (actPr > actN * 5 * 0.6f) {
                    System.out.print("\n" + new TimeUtil().getTimeStr(curTime)
                            + "有体动了：actCount::" + actCount + "::turnCount::"
                            + turnCount);
                    actCount++;// 体动次数
                    sendMsg(CusConstant.ACT_COUNT, actCount);//发送体动次数
                    if (crest > 200) {
                        turnCount++;
                        sendMsg(CusConstant.TRUN_COUNT, turnCount);//发送翻身次数
                    }
                }
            }
            // System.out.print("\n" + " crest：" + crest + " op：" + op
            // + " curWave32:" + curWave32 + " curWave64:" + curWave64
            // + " sumcurWave32:" + sumcurWave32 + " sumcurWave64:"
            // + sumcurWave64 + " pensent" + pensent);
            sumcurWave32 = 0;
            sumcurWave64 = 0;
            actPr = 0;// 每100毫秒的计数
            actN = 0;// 有多少条数据
        } else if (curWave32 != 0) {
            // System.out.print("\n" +" crest：" + crest + " op：" + op
            // + " curWave32:" + curWave32 + " curWave64:" + curWave64
            // + " sumcurWave32:" + sumcurWave32 + " sumcurWave64:"
            // + sumcurWave64 + " pensent" + pensent);
        }
        lastWave = curWave32;// 保存最后累计值

    }

    /**
     * 计算止鼾等级
     */
    private void clacStopSnoreLV(long durTime) {
        if (durTime > 600000) {//十分钟间隔
            vbLv = MySharedPreferencesUtil.getVbLv(context);
            long time = System.currentTimeMillis() - startTime;
            if (time < Hour * 2) {
                if (vbLv - 2 > 0) {
                    vbLv = vbLv - 2;
                } else {
                    vbLv = 1;
                }
            }
            if (time > Hour * 2 && time < Hour * 4) {
                if (vbLv - 3 > 0) {
                    vbLv = vbLv - 3;
                } else {
                    vbLv = 1;
                }
            }
            if (time > Hour * 4 && time < Hour * 6) {
                if (vbLv - 4 > 0) {
                    vbLv = vbLv - 4;
                } else {
                    vbLv = 1;
                }
            }
            if (time > Hour * 6) {
                if (vbLv - 5 > 0) {
                    vbLv = vbLv - 5;
                } else {
                    vbLv = 1;
                }
            }

        }
    }

    /**
     * 发送消息
     */
    private void sendMsg(int w, Object v) {
        Message msg = new Message();
        msg.what = w;
        msg.obj = v;
        handler.sendMessage(msg);
    }

    public int getSnoreCount() {
        return snoreCount;
    }

    public void setSnoreCount(int snoreCount) {
        this.snoreCount = snoreCount;
    }

    public boolean isSnore() {
        return isSnore;
    }

    public void setSnore(boolean isSnore) {
        this.isSnore = isSnore;
    }

    public int getSumcurWave32() {
        return sumcurWave32;
    }

    public void setSumcurWave32(int sumcurWave32) {
        this.sumcurWave32 = sumcurWave32;
    }

    public int getSumcurWave64() {
        return sumcurWave64;
    }

    public void setSumcurWave64(int sumcurWave64) {
        this.sumcurWave64 = sumcurWave64;
    }

    public int getLastWave() {
        return lastWave;
    }

    public void setLastWave(int lastWave) {
        this.lastWave = lastWave;
    }

    public long getLastStart() {
        return lastStart;
    }

    public void setLastStart(long lastStart) {
        this.lastStart = lastStart;
    }

    public long getLastEnd() {
        return lastEnd;
    }

    public void setLastEnd(long lastEnd) {
        this.lastEnd = lastEnd;
    }

    public double[] getOpHB() {
        return opHB;
    }

    public void setOpHB(double[] opHB) {
        this.opHB = opHB;
    }

    public long getCurEnd() {
        return curEnd;
    }

    public void setCurEnd(long curEnd) {
        this.curEnd = curEnd;
    }

    public long getCrest() {
        return crest;
    }

    public void setCrest(long crest) {
        this.crest = crest;
    }

    public long getCycle() {
        return cycle;
    }

    public void setCycle(long cycle) {
        this.cycle = cycle;
    }

    public int getCurWave32() {
        return curWave32;
    }

    public void setCurWave32(int curWave32) {
        this.curWave32 = curWave32;
    }

    public int getCurWave64() {
        return curWave64;
    }

    public void setCurWave64(int curWave64) {
        this.curWave64 = curWave64;
    }

    public float getPensent() {
        return pensent;
    }

    public void setPensent(float pensent) {
        this.pensent = pensent;
    }

    public int getSnoreCountN() {
        return snoreCountN;
    }

    public void setSnoreCountN(int snoreCountN) {
        this.snoreCountN = snoreCountN;
    }

    public double getOp() {
        return op;
    }

    public void setOp(double op) {
        this.op = op;
    }

    public int[] getSpectremS() {
        return spectremS;
    }

    public int getStopSnoreCount() {
        return stopSnoreCount;
    }

    public void setSpectremS(int[] spectremS) {
        this.spectremS = spectremS;
    }

}
